package top.aigoo.project01.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import top.aigoo.project01.entity.Product;
import top.aigoo.project01.entity.ProductImg;
import top.aigoo.project01.entity.dto.ImageHolder;
import top.aigoo.project01.entity.dto.ProductExecution;
import top.aigoo.project01.enums.ProductStateEnum;
import top.aigoo.project01.mapper.ProductImgMapper;
import top.aigoo.project01.mapper.ProductMapper;
import top.aigoo.project01.service.ProductService;
import top.aigoo.project01.utils.ImageUtil;
import top.aigoo.project01.utils.PageCalculator;
import top.aigoo.project01.utils.PathUtil;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Description: 请填写该类完成的功能
 * @Author: Mr.OYSHUO.欧阳大叔  mail:1642302522@qq.com
 * @Version 1.0.0
 * @Date: 2021/8/27 23:33
 */

@Service
public class ProductServiceImpl implements ProductService {
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private ProductImgMapper productImgMapper;

    /**
     * 更新商品的业务逻辑
     * 1.如果缩略图参数有值，则处理缩略图，若原先存在缩略图则先删除再添加新图,之后获取缩略图相对路径并赋值给product
     * 2.若商品详情图列表参数有值，则商品详情图片列表进行同样操作，
     * 3.将tb_product_img下面的该商品原来的商品详情图记录全部清除
     * 4.更新tb_product的信息
     */
    @Override
    @Transactional
    public ProductExecution modifyProduct(Product product, CommonsMultipartFile thumbnail, List<CommonsMultipartFile> productImgs) {
        //空值判断
        if (product != null && product.getShop() != null && product.getShop().getShopId() != null) {
            // 给商品设置默认属性
            //product.setUpdateTime(new Date());

            //如果商品缩略图不为空并且原来的缩略图也不为空 则删除原来缩略图并添加
            if (thumbnail != null) {
                // 先获取一遍原来信息，因为原来的信息里有原图片的地址
                Product tempProduct = productMapper.queryProductById(product.getProductId());

                if (tempProduct.getImgAddr() != null) {
                    ImageUtil.deleteFileOrPath(tempProduct.getImgAddr());
                }
                ImageHolder imageHolder = null;
                try {
                    imageHolder = new ImageHolder(thumbnail.getOriginalFilename(), thumbnail.getInputStream());
                } catch (IOException e) {
                    throw new RuntimeException("更新商品信息失败:" + e.toString());
                }
                // 调用方法将图片存到硬盘并将地址设置到product中
                addThumbnail(product, imageHolder);
            }

            // 如果有新存入的商品详情图，则将原先的删除，并添加新的图片
            if (productImgs != null && productImgs.size() > 0) {
                // 先删掉原来的图片
                deleteProductImgs(product.getProductId());
                //再添加新的图片
                addProductImgs(product, productImgs);
            }

            try {
                int effectedNum = productMapper.updateProduct(product);
                if (effectedNum <= 0) {
                    throw new RuntimeException("更新商品信息失败");
                }
                return new ProductExecution(ProductStateEnum.SUCCESS, product);
            } catch (Exception e) {
                throw new RuntimeException("更新商品信息失败:" + e.toString());
            }


        } else {
            return new ProductExecution(ProductStateEnum.EMPTY);
        }

    }

    /**
     * 先删除该商品的所有在硬盘上的详情图，
     * 再去删除该商品在数据库上的详情图记录
     *
     * @param productId
     */
    private void deleteProductImgs(long productId) {
        //1.先取出来所有图片
        List<ProductImg> productImgList = productImgMapper.queryProductImgList(productId);
        //2.删除掉硬盘上原来图片
        for (ProductImg productImg : productImgList) {
            ImageUtil.deleteFileOrPath(productImg.getImgAddr());
        }
        //3.删除掉数据库里原有图片的信息
        productImgMapper.deleteProductImgByProductId(productId);
    }

    /**
     * 批量添加商品详情图片
     */

    private void addProductImgs(Product product, List<CommonsMultipartFile> productImgs) {

        String dest = PathUtil.getShopImagePath(product.getShop().getShopId());
        //传入详情图片列表和目标存储路径，返货imgAddrList
        List<String> imgAddrList = ImageUtil.generateNormalImgs(productImgs, dest);

        if (imgAddrList != null && imgAddrList.size() > 0) {
            List<ProductImg> productImgList = new ArrayList<ProductImg>();
            for (String imgAddr : imgAddrList) {
                ProductImg productImg = new ProductImg();
                productImg.setImgAddr(imgAddr);
                productImg.setProductId(product.getProductId());
                productImgList.add(productImg);
            }
            // 批量将数据插入到数据库
            try {
                int effectedNum = productImgMapper.batchInsertProductImg(productImgList);
                if (effectedNum <= 0) {
                    throw new RuntimeException("创建商品详情图片失败");
                }
            } catch (Exception e) {
                throw new RuntimeException("创建商品详情图片失败:" + e.toString());
            }
        }
    }

    /**
     * 根据商品id获取商品信息
     * @param productId
     * @return
     */
    @Override
    public Product getProductById(long productId) {
        return productMapper.queryProductById(productId);
    }

    /**
     * 查询商品列表并分页，可输入的条件有：商品名（模糊），商品状态，店铺Id,商品类别
     *
     * @param productCondition
     * @param pageIndex 获取那一页
     * @param pageSize 每页获取多少
     * @return
     */
    @Override
    @Transactional
    public ProductExecution getProductList(Product productCondition, int pageIndex, int pageSize) {
        // 页码转换成数据库行码,并调用dao层取回指定页码的商品列表
        int rowIndex = PageCalculator.calculateRowIndex(pageIndex, pageSize);
        List<Product> productList = productMapper.queryProductList(productCondition, rowIndex, pageSize);
        //基于同样的查询条件返回该查询条件下的商品总数
        int count = productMapper.queryProductCount(productCondition);

        ProductExecution pe = new ProductExecution();
        pe.setProductList(productList);
        pe.setCount(count);
        return pe;
    }

    /**
     * 1.处理缩略图，获取缩略图相对路径并赋值给product
     * 2.往tb_product写入商品信息，获取productId
     * 3.结合productId批量处理商品详情图
     * 4.将商品详情图列表批量插入tb_product_img中
     */
    @Override
    @Transactional
    public ProductExecution addProduct(Product product, ImageHolder thumbnail, List<ImageHolder> productImgList) throws RuntimeException {
        // 1,空值判断
        if (product != null && product.getShop() != null && product.getShop().getShopId() != null) {
            //给商品设置默认属性
            product.setEnableStatus(1); //默认为商品上架的状态
            //2.保存上传的缩略图到服务器并将保存后的地址放入到product中，商品缩略图不为空则不添加
            if (thumbnail != null) {
                addThumbnail(product, thumbnail);
            }
            //3.创建商品信息，添加商品
            try {
                int effectedNum = productMapper.insertProduct(product);
                if (effectedNum <= 0) {
                    throw new RuntimeException("创建商品失败!");
                }
            } catch (Exception e) {
                throw new RuntimeException("创建商品失败" + e.toString());
            }
            //4.处理添加商品详情图，若商品详情图不为空就添加
            if (productImgList != null && productImgList.size() > 0) {
                addProductImgList(product, productImgList);
            }
            return new ProductExecution(ProductStateEnum.SUCCESS, product);
        } else {
            return new ProductExecution(ProductStateEnum.EMPTY);
        }
    }

    /**
     * 批量添加商品详情图片
     *
     * @param product
     * @param productImgListHold
     */
    private void addProductImgList(Product product, List<ImageHolder> productImgListHold) {
        // 1. 获取图片存储路径，这里直接存放到响应店铺的文件夹底下
        String dest = PathUtil.getShopImagePath(product.getShop().getShopId());

        List<ProductImg> productImgList = new ArrayList<ProductImg>();
        //遍历图片一次去处理，并添加进productImg实体类里面
        for (ImageHolder productImgHolder : productImgListHold) {
            //将图片保存到服务器,并返回相对路径
            String imgAddr = ImageUtil.generateNormalImg(productImgHolder, dest);
            ProductImg productImg = new ProductImg();
            productImg.setImgAddr(imgAddr);
            productImg.setProductId(product.getProductId());

            productImgList.add(productImg);
        }

        // 遍历图片一次去处理，并添加进productImg实体类里面，如果确实有图片需要添加，就执行批处理操作
        if (productImgList.size() > 0) {
            try {
                int effectedNum = productImgMapper.batchInsertProductImg(productImgList);
                if (effectedNum <= 0) {
                    throw new RuntimeException("创建商品详情图片失败");
                }
            } catch (Exception e) {
                throw new RuntimeException("创建商品详情图片失败:" + e.toString());
            }
        }


    }

    /**
     * 接收用户上传的商品缩略图并保存到服务器，并将图片的服务器相对地址保存到商品信息中
     *
     * @param product
     * @param thumbnail
     */
    private void addThumbnail(Product product, ImageHolder thumbnail) {
        //获取文件基础路径，既目标存放路径
        String targetAddr = PathUtil.getShopImagePath(product.getShop().getShopId());
        // 将图片保存到服务器并生成图片的相对路径
        String thumbnailAddr = ImageUtil.generateThumbnail(thumbnail, targetAddr);
        //3 写入到product
        product.setImgAddr(thumbnailAddr);
    }
}
